package com.example.myapplication;

import android.content.Context;
import android.util.Log;

import com.google.gson.Gson;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * 统一的HTTP请求封装类
 * 基于OkHttp3实现
 */
public class OKHttpClass {
    
    private static final String TAG = "OKHttpClass";
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType FORM = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
    
    private static OKHttpClass instance;
    private OkHttpClient client;
    private Gson gson;
    private Context context;
    
    // 默认配置
    private static final int CONNECT_TIMEOUT = 10; // 连接超时（秒）
    private static final int READ_TIMEOUT = 30; // 读取超时（秒）
    private static final int WRITE_TIMEOUT = 30; // 写入超时（秒）
    
    private OKHttpClass(Context context) {
        this.context = context.getApplicationContext();
        this.gson = new Gson();
        initOkHttpClient();
    }
    
    /**
     * 获取单例实例
     */
    public static synchronized OKHttpClass getInstance(Context context) {
        if (instance == null) {
            instance = new OKHttpClass(context);
        }
        return instance;
    }
    
    /**
     * 初始化OkHttpClient
     */
    private void initOkHttpClient() {
        // 日志拦截器
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.d(TAG, message);
            }
        });
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        
        // 创建信任所有证书的 TrustManager
        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    // 不验证客户端证书
                }
                
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    // 不验证服务器证书
                }
                
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[]{};
                }
            }
        };
        
        // 创建SSLContext并初始化
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (Exception e) {
            Log.e(TAG, "创建SSLContext失败", e);
        }
        
        // 创建不验证主机名的 HostnameVerifier
        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                // 不验证主机名，直接返回true
                return true;
            }
        };
        
        // 创建OkHttpClient Builder
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                .addInterceptor(loggingInterceptor)
                .retryOnConnectionFailure(true) // 自动重试
                .hostnameVerifier(hostnameVerifier); // 不验证主机名
        
        // 如果SSLContext创建成功，设置SSL Socket Factory
        if (sslContext != null) {
            clientBuilder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]);
        }
        
        // 创建OkHttpClient
        client = clientBuilder.build();
    }
    
    /**
     * GET请求（异步）
     */
    public void get(String url, Map<String, String> headers, HttpCallback callback) {
        Request.Builder requestBuilder = new Request.Builder().url(url);
        
        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        
        Request request = requestBuilder.build();
        
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (callback != null) {
                    callback.onFailure(e.getMessage());
                }
            }
            
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String body = response.body() != null ? response.body().string() : "";
                    if (callback != null) {
                        callback.onSuccess(response.code(), body);
                    }
                } else {
                    String errorMsg = response.body() != null ? response.body().string() : "请求失败";
                    if (callback != null) {
                        callback.onFailure("HTTP " + response.code() + ": " + errorMsg);
                    }
                }
            }
        });
    }
    
    /**
     * GET请求（同步）
     */
    public HttpResponse getSync(String url, Map<String, String> headers) {
        Request.Builder requestBuilder = new Request.Builder().url(url);
        
        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        
        Request request = requestBuilder.build();
        
        try {
            Response response = client.newCall(request).execute();
            String body = response.body() != null ? response.body().string() : "";
            return new HttpResponse(response.isSuccessful(), response.code(), body, null);
        } catch (IOException e) {
            return new HttpResponse(false, -1, null, e.getMessage());
        }
    }
    
    /**
     * POST请求（JSON，异步）
     */
    public void postJson(String url, Map<String, String> headers, Object data, HttpCallback callback) {
        String json = gson.toJson(data);
        RequestBody body = RequestBody.create(json, JSON);
        
        Request.Builder requestBuilder = new Request.Builder()
                .url(url)
                .post(body);
        
        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        
        Request request = requestBuilder.build();
        
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (callback != null) {
                    callback.onFailure(e.getMessage());
                }
            }
            
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String responseBody = response.body() != null ? response.body().string() : "";
                    if (callback != null) {
                        callback.onSuccess(response.code(), responseBody);
                    }
                } else {
                    String errorMsg = response.body() != null ? response.body().string() : "请求失败";
                    if (callback != null) {
                        callback.onFailure("HTTP " + response.code() + ": " + errorMsg);
                    }
                }
            }
        });
    }
    
    /**
     * POST请求（JSON，同步）
     */
    public HttpResponse postJsonSync(String url, Map<String, String> headers, Object data) {
        String json = gson.toJson(data);
        RequestBody body = RequestBody.create(json, JSON);
        
        Request.Builder requestBuilder = new Request.Builder()
                .url(url)
                .post(body);
        
        // 添加请求头
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        
        Request request = requestBuilder.build();
        
        try {
            Response response = client.newCall(request).execute();
            String responseBody = response.body() != null ? response.body().string() : "";
            return new HttpResponse(response.isSuccessful(), response.code(), responseBody, null);
        } catch (IOException e) {
            return new HttpResponse(false, -1, null, e.getMessage());
        }
    }
    
    /**
     * 下载文件（支持断点续传）
     */
    public void downloadFile(String url, String filePath, long downloadedSize, DownloadCallback callback) {
        if (url == null || url.isEmpty()) {
            if (callback != null) {
                callback.onError("下载URL为空");
            }
            return;
        }
        
        if (filePath == null || filePath.isEmpty()) {
            if (callback != null) {
                callback.onError("文件路径为空");
            }
            return;
        }
        Request.Builder requestBuilder = new Request.Builder().url(url);
        
        // 如果已有下载进度，添加Range头（断点续传）
        if (downloadedSize > 0) {
            requestBuilder.addHeader("Range", "bytes=" + downloadedSize + "-");
        }
        
        Request request = requestBuilder.build();
        
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (callback != null) {
                    callback.onError(e.getMessage());
                }
            }
            
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) {
                    if (callback != null) {
                        callback.onError("下载失败，状态码: " + response.code());
                    }
                    return;
                }
                
                ResponseBody body = response.body();
                if (body == null) {
                    if (callback != null) {
                        callback.onError("响应体为空");
                    }
                    return;
                }
                
                long contentLength = body.contentLength();
                long totalLength = downloadedSize + contentLength;
                
                // 创建文件目录
                File file = new File(filePath);
                File parentDir = file.getParentFile();
                if (parentDir != null && !parentDir.exists()) {
                    parentDir.mkdirs();
                }
                
                // 写入文件
                try (InputStream inputStream = body.byteStream();
                     FileOutputStream outputStream = new FileOutputStream(file, downloadedSize > 0)) {
                    
                    byte[] buffer = new byte[8192];
                    long totalBytesRead = downloadedSize;
                    int bytesRead;
                    long lastProgressUpdate = System.currentTimeMillis();
                    
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                        totalBytesRead += bytesRead;
                        
                        // 限制进度更新频率（每500ms更新一次）
                        long currentTime = System.currentTimeMillis();
                        if (callback != null && totalLength > 0 &&
                            (currentTime - lastProgressUpdate > 500 || totalBytesRead == totalLength)) {
                            int progress = (int) (totalBytesRead * 100 / totalLength);
                            callback.onProgress(progress, totalBytesRead, totalLength);
                            lastProgressUpdate = currentTime;
                        }
                    }
                    
                    outputStream.flush();
                    outputStream.getFD().sync();
                    
                    if (callback != null) {
                        callback.onSuccess(filePath);
                    }
                } catch (IOException e) {
                    if (callback != null) {
                        callback.onError("文件写入失败: " + e.getMessage());
                    }
                }
            }
        });
    }
    
    /**
     * HTTP回调接口
     */
    public interface HttpCallback {
        void onSuccess(int code, String response);
        void onFailure(String error);
    }
    
    /**
     * 下载回调接口
     */
    public interface DownloadCallback {
        void onProgress(int progress, long downloaded, long total);
        void onSuccess(String filePath);
        void onError(String error);
    }
    
    /**
     * HTTP响应结果
     */
    public static class HttpResponse {
        private final boolean success;
        private final int code;
        private final String body;
        private final String error;
        
        public HttpResponse(boolean success, int code, String body, String error) {
            this.success = success;
            this.code = code;
            this.body = body;
            this.error = error;
        }
        
        public boolean isSuccess() {
            return success;
        }
        
        public int getCode() {
            return code;
        }
        
        public String getBody() {
            return body;
        }
        
        public String getError() {
            return error;
        }
    }
}

